<?php


abstract class vic_Base
{
    protected $attributes;


    public function __construct()
    {
        $this->attributes = array();
    }


    public function serialize($name = '', $_this = false, $attributes = array())
    {
        if ($name == '')
            $name = $this->className();

        $attributes = array_merge($this->attributes, $attributes);
        $body = '';
        if ($_this !== false)
            $body .= $_this->serialize('_this');
        $body .= $this->serializeBody();

        if ($body != '')
        {
            $msg = '<' . $name .
                $this->serializeAttributes($attributes) . '>' .
                $body . '</' . $name . '>';
        }
        else
        {
            $msg = '<' . $name .
                $this->serializeAttributes($attributes) . ' />';
        }

        return $msg;
    }

    protected function serializeAttributes($attributes)
    {
        $attrs = '';

        foreach ($attributes as $k => $v)
        {
            $attrs = ' ' . $k . '=' . '"' . $this->encodeValue($v) . '"';
        }

        return $attrs;
    }

    protected function serializeValue($name, $value)
    {
        if (is_object($value))
        {
            if (is_a($value, 'vic_Base'))
                return $value->serialize($name);

            throw new Exception('Cannot encode class of type ' . get_class($value));
        }

        if (is_array($value))
        {
            $text = '';

            if (is_assoc($value))
            {
                foreach ($value as $k => $v)
                {
                    $text .= $this->serializeValue($k, $v);
                }
            }
            else
            {
                foreach ($value as $k => $v)
                {
                    $text .= $this->serializeValue($name, $v);
                }
            }

            return $text;
        }

        return '<' . $name . '>' . $this->encodeValue($value) .
            '</' . $name . '>';
    }

    function encodeValue($val)
    {
        $val = str_replace('&', '&amp;', $val);
        $val = str_replace("'", '&apos;', $val);
        $val = str_replace('"', '&quot;', $val);
        $val = str_replace('<', '&lt;', $val);
        $val = str_replace('>', '&gt;', $val);

        return $val;   
    }

    protected function className()
    {
        return str_replace('vic_', '', get_class($this));
    }


    abstract protected function serializeBody();
}


class vi_Message extends vic_Base
{
    protected $name;
    protected $parameters;


    public function __construct($name, $parms = array())
    {
        parent::__construct();

        $this->name = $name;
        $this->parameters = $parms;
    }


    protected function serializeBody()
    {
        return $this->serializeValue('', $this->parameters);
    }


    protected function className()
    {
        return $this->name;
    }
}


abstract class vi_Service
{
    protected $svc;
    protected $ref;


    public function __construct($service, $serviceName)
    {
        $this->svc = $service;
        $this->ref = $serviceName;
    }


    protected function ServiceType()
    {
        return str_replace('vi_', '', get_class($this));
    }


    protected function ServiceReference()
    {
        return new vic_ManagedObjectReference($this->ServiceType(), $this->ref);
    }
}


class vic_ManagedObjectReference extends vic_Base
{
    protected $instance;
    public $properties;


    public function __construct($type, $inst, $initialproperties = array())
    {
        parent::__construct();

        $this->attributes['type'] = $type;
        $this->instance = $inst;
        $this->properties = $initialproperties;
    }

    protected function serializeBody()
    {
        return $this->encodeValue($this->instance);
    }

    public function GetType()
    {
        return $this->attributes['type'];
    }

    public function GetInstance()
    {
        return $this->instance;
    }


    static public function Folder($name, $properties = array())
    {
        return new vic_ManagedObjectReference('Folder', $name, $properties);
    }

    static public function Datacenter($name, $properties = array())
    {
        return new vic_ManagedObjectReference('Datacenter', $name, $properties);
    }

    static public function ClusterComputeResource($name, $properties = array())
    {
        return new vic_ManagedObjectReference('ClusterComputeResource', $name, $properties);
    }

    static public function HostSystem($name, $properties = array())
    {
        return new vic_ManagedObjectReference('HostSystem', $name, $properties);
    }

    static public function VirtualMachine($name, $properties = array())
    {
        return new vic_ManagedObjectReference('VirtualMachine', $name, $properties);
    }
}


class vic_PropertyFilterSpec extends vic_Base
{
    public $objectSet;
    public $propSet;

    public function __construct($object, $prop)
    {
        parent::__construct();
        $this->objectSet = (is_array($object) ? $object : array($object));
        $this->propSet = (is_array($prop) ? $prop : array($prop));
    }

    protected function serializeBody()
    {
        return $this->serializeValue('propSet', $this->propSet) .
               $this->serializeValue('objectSet', $this->objectSet);
    }
}


class vic_SelectionSpec extends vic_Base
{
    public $name;


    public function __construct($name)
    {
        parent::__construct();
        $this->name = $name;
    }

    protected function serializeBody()
    {
        return $this->serializeValue('name', $this->name);
    }
}


class vic_TraversalSpec extends vic_SelectionSpec
{
    protected $path;
    protected $selectSet;
    protected $skip;
    protected $type;


    public function __construct($name, $type, $path, $skip = 0, $selectSet = array())
    {
        parent::__construct($name);
        $this->attributes['xsi:type'] = 'TraversalSpec';
        $this->path = $path;
        $this->skip = $skip;
        $this->type = $type;
        $this->selectSet = (is_array($selectSet) ? $selectSet : array($selectSet));
    }


    protected function serializeBody()
    {
        $body = parent::serializeBody();
        $body .= $this->serializeValue('type', $this->type);
        $body .= $this->serializeValue('path', $this->path);
        $body .= $this->serializeValue('skip', $this->skip);
        if (count($this->selectSet) > 0)
            $body .= $this->serializeValue('selectSet', $this->selectSet);

        return $body;
    }


    public static function deepFolderTraversalSpecs()
    {
        $selectSet = array();

        $selectSet[] = vic_TraversalSpec::folderTraversalSpec('childEntity', true);
        $selectSet[] = vic_TraversalSpec::datacenterDatastoreTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::datacenterNetworkTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::datacenterVmTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::datacenterHostTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::computeResourceHostTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::computeResourceRpTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::resourcePoolTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::hostVmTraversalSpec(true);
        $selectSet[] = vic_TraversalSpec::resourcePoolVmTraversalSpec(true);

        return $selectSet;
    }

    public static function folderTraversalSpec($path = 'childEntity', $recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
        {
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('datacenterHostTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('datacenterVmTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('datacenterDatastoreTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('datacenterNetworkTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('computeResourceRpTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('computeResourceHostTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('hostVmTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('resourcePoolTraversalSpec');
        }

        return new vic_TraversalSpec('folderTraversalSpec',
            'Folder', $path, 0, $selectSet);
    }

    public static function datacenterDatastoreTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');

        return new vic_TraversalSpec('datacenterDatastoreTraversalSpec',
            'Datacenter', 'datastoreFolder', 0, $selectSet);
    }

    public static function datacenterNetworkTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');

        return new vic_TraversalSpec('datacenterNetworkTraversalSpec',
            'Datacenter', 'networkFolder', 0, $selectSet);
    }

    public static function datacenterVmTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');

        return new vic_TraversalSpec('datacenterVmTraversalSpec',
            'Datacenter', 'vmFolder', 0, $selectSet);
    }

    public static function datacenterHostTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');

        return new vic_TraversalSpec('datacenterHostTraversalSpec',
            'Datacenter', 'hostFolder', 0, $selectSet);
    }

    public static function computeResourceHostTraversalSpec()
    {
        return new vic_TraversalSpec('computeResourceHostTraversalSpec',
            'ComputeResource', 'host');
    }

    public static function computeResourceRpTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
        {
            $selectSet[] = new vic_SelectionSpec('resourcePoolTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('resourcePoolVmTraversalSpec');
        }

        return new vic_TraversalSpec('computeResourceRpTraversalSpec',
            'ComputeResource', 'resourcePool', 0, $selectSet);
    }

    public static function resourcePoolTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
        {
            $selectSet[] = new vic_SelectionSpec('resourcePoolTraversalSpec');
            $selectSet[] = new vic_SelectionSpec('resourcePoolVmTraversalSpec');
        }

        return new vic_TraversalSpec('resourcePoolTraversalSpec',
            'ResourcePool', 'resourcePool', 0, $selectSet);
    }

    public static function hostVmTraversalSpec($recursive = false)
    {
        $selectSet = array();
        if ($recursive === true)
            $selectSet[] = new vic_SelectionSpec('folderTraversalSpec');

        return new vic_TraversalSpec('hostVmTraversalSpec',
            'HostSystem', 'vm', 0, $selectSet);
    }

    public static function resourcePoolVmTraversalSpec()
    {
        return new vic_TraversalSpec('resourcePoolVmTraversalSpec',
            'ResourcePool', 'vm');
    }
}


class vic_ObjectSpec extends vic_Base
{
    public $obj;
    public $skip;
    public $selectSet;

    public function __construct($obj, $skip = 0, $select = array())
    {
        parent::__construct();
        $this->obj = $obj;
        $this->skip = $skip;
        $this->selectSet = (is_array($select) ? $select : array($select));
    }

    protected function serializeBody()
    {
        $body = $this->serializeValue('obj', $this->obj);
        $body .= $this->serializeValue('skip', $this->skip);
        if (count($this->selectSet) > 0)
            $body .= $this->serializeValue('selectSet', $this->selectSet);

        return $body;
    }
}


class vic_PropertySpec extends vic_Base
{
    public $all;
    public $pathSet;
    public $type;


    public function __construct($type, $all = 0, $path = array())
    {
        parent::__construct();
        $this->all = $all;
        $this->pathSet = (is_array($path) ? $path : array($path));
        $this->type = $type;
    }

    protected function serializeBody()
    {
        return $this->serializeValue('type', $this->type) .
               $this->serializeValue('all', $this->all) .
               $this->serializeValue('pathSet', $this->pathSet);
    }
}


class vic_Enum
{
    const AS_HTML = 1;
    const AS_IMAGE = 2;


    public static function ManagedEntityStatus($value, $as = vic_Enum::AS_HTML, $options = array())
    {
        $result = '';
        $classes = (isset($options['class']) ? ' ' . $options['class'] : '');

        if ($value == 'green')
        {
            if ($as == self::AS_HTML)
                $result = '<span class="greenStatus' . $classes . '">Green</span>';
            else if ($as == self::AS_IMAGE)
                $result = '<img class="greenStatus' . $classes . '" src="images/greenStatus.png" alt="Green" />';
        }
        else if ($value == 'yellow')
        {
            if ($as == self::AS_HTML)
                $result = '<span class="yellowStatus' . $classes . '">Yellow</span>';
            else if ($as == self::AS_IMAGE)
                $result = '<img class="yellowStatus' . $classes . '" src="images/yellowStatus.png" alt="Yellow" />';
        }
        else if ($value == 'red')
        {
            if ($as == self::AS_HTML)
                $result = '<span class="redStatus' . $classes . '">Red</span>';
            else if ($as == self::AS_IMAGE)
                $result = '<img class="redStatus' . $classes . '" src="images/redStatus.png" alt="Red" />';
        }
        else
        {
            if ($as == self::AS_HTML)
                $result = '<span class="unknownStatus' . $classes . '">Unknown</span>';
            else if ($as == self::AS_IMAGE)
                $result = '<img class="unknownStatus' . $classes . '" src="images/unknownStatus.png" alt="Unknown" />';
        }

        return $result;
    }
}


?>
